From 240cd0b99485fb9de00a63ad254bf55a5fa75aea Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C3=98yvind=20Kol=C3=A5s?= Date: Thu, 5 Apr 2018 23:24:31 +0200 Subject: [PATCH] extensions: add a double extension This will permit slightly faster than the generic fast paths for some possibly desired intermediate conversions. This also adds alpha stripping - which fills in the last babl fast path currently reported missing on every launch of GIMP. --- extensions/Makefile.am | 3 +- extensions/double.c | 264 +++++++++++++++++++++++++++++++++++ extensions/gggl-table-lies.c | 52 +++++++ extensions/gggl-table.c | 1 + extensions/meson.build | 1 + extensions/two-table.c | 11 ++ 6 files changed, 331 insertions(+), 1 deletion(-) create mode 100644 extensions/double.c diff --git a/extensions/Makefile.am b/extensions/Makefile.am index b103c93..06d6bea 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -18,7 +18,7 @@ ext_LTLIBRARIES = \ 16bit.la \ cairo.la \ CIE.la \ - float-half.la \ + float-half.la \ gegl-fixups.la \ gggl-lies.la \ gggl-table.la \ @@ -26,6 +26,7 @@ ext_LTLIBRARIES = \ gggl.la \ gimp-8bit.la \ grey.la \ + double.la \ float.la \ fast-float.la \ naive-CMYK.la \ diff --git a/extensions/double.c b/extensions/double.c new file mode 100644 index 0000000..f592cb9 --- /dev/null +++ b/extensions/double.c @@ -0,0 +1,264 @@ +/* babl - dynamically extendable universal pixel conversion library. + * Copyright (C) 2012, Øyvind Kolås + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see + * . + */ + +#include "config.h" + +#include +#include + +#include "babl-internal.h" +#include "babl-cpuaccel.h" +#include "extensions/util.h" +#include "base/util.h" + + +#define INLINE inline + + +static INLINE void +conv_rgbaD_linear_rgbAD_gamma (const Babl *conversion,unsigned char *src, + unsigned char *dst, + long samples) +{ + const Babl *space = babl_conversion_get_destination_space (conversion); + const Babl **trc = (void*)space->space.trc; + + double *fsrc = (double *) src; + double *fdst = (double *) dst; + int n = samples; + + while (n--) + { + double alpha = fsrc[3]; + *fdst++ = babl_trc_from_linear (trc[0], *fsrc++) * alpha; + *fdst++ = babl_trc_from_linear (trc[1], *fsrc++) * alpha; + *fdst++ = babl_trc_from_linear (trc[2], *fsrc++) * alpha; + *fdst++ = *fsrc++; + } +} + +static INLINE void +conv_rgbAD_linear_rgbAD_gamma (const Babl *conversion, + unsigned char *src, + unsigned char *dst, + long samples) +{ + const Babl *space = babl_conversion_get_destination_space (conversion); + const Babl **trc = (void*)space->space.trc; + + double *fsrc = (double *) src; + double *fdst = (double *) dst; + int n = samples; + + while (n--) + { + double alpha = fsrc[3]; + if (alpha < BABL_ALPHA_THRESHOLD) + { + *fdst++ = 0.0; + *fdst++ = 0.0; + *fdst++ = 0.0; + *fdst++ = 0.0; + fsrc+=4; + } + else if (alpha >= 1.0) + { + *fdst++ = babl_trc_from_linear (trc[0], *fsrc++) * alpha; + *fdst++ = babl_trc_from_linear (trc[1], *fsrc++) * alpha; + *fdst++ = babl_trc_from_linear (trc[2], *fsrc++) * alpha; + *fdst++ = *fsrc++; + } + else + { + double alpha_recip = 1.0 / alpha; + *fdst++ = babl_trc_from_linear (trc[0], *fsrc++ * alpha_recip) * alpha; + *fdst++ = babl_trc_from_linear (trc[1], *fsrc++ * alpha_recip) * alpha; + *fdst++ = babl_trc_from_linear (trc[2], *fsrc++ * alpha_recip) * alpha; + *fdst++ = *fsrc++; + } + } +} + +static INLINE void +conv_rgbaD_linear_rgbaD_gamma (const Babl *conversion,unsigned char *src, + unsigned char *dst, + long samples) +{ + const Babl *space = babl_conversion_get_destination_space (conversion); + const Babl **trc = (void*)space->space.trc; + + double *fsrc = (double *) src; + double *fdst = (double *) dst; + int n = samples; + + while (n--) + { + *fdst++ = babl_trc_from_linear (trc[0], *fsrc++); + *fdst++ = babl_trc_from_linear (trc[1], *fsrc++); + *fdst++ = babl_trc_from_linear (trc[2], *fsrc++); + *fdst++ = *fsrc++; + } +} + +#define conv_rgbaD_linear_rgbD_linear conv_rgbaD_gamma_rgbD_gamma + +static void +conv_rgbaD_linear_rgbD_linear (const Babl *conversion,unsigned char *src, + unsigned char *dst, + long samples) +{ + double *fsrc = (double *) src; + double *fdst = (double *) dst; + int n = samples; + + while (n--) + { + *fdst++ = *fsrc++; + *fdst++ = *fsrc++; + *fdst++ = *fsrc++; + fsrc++; + } +} + + +static INLINE void +conv_rgbD_linear_rgbD_gamma (const Babl *conversion,unsigned char *src, + unsigned char *dst, + long samples) +{ + const Babl *space = babl_conversion_get_destination_space (conversion); + const Babl **trc = (void*)space->space.trc; + double *fsrc = (double *) src; + double *fdst = (double *) dst; + int n = samples; + + while (n--) + { + *fdst++ = babl_trc_from_linear (trc[0], *fsrc++); + *fdst++ = babl_trc_from_linear (trc[1], *fsrc++); + *fdst++ = babl_trc_from_linear (trc[2], *fsrc++); + } +} + + +static INLINE void +conv_rgbaD_gamma_rgbaD_linear (const Babl *conversion,unsigned char *src, + unsigned char *dst, + long samples) +{ + const Babl *space = babl_conversion_get_destination_space (conversion); + const Babl **trc = (void*)space->space.trc; + double *fsrc = (double *) src; + double *fdst = (double *) dst; + int n = samples; + + while (n--) + { + *fdst++ = babl_trc_to_linear (trc[0], *fsrc++); + *fdst++ = babl_trc_to_linear (trc[1], *fsrc++); + *fdst++ = babl_trc_to_linear (trc[2], *fsrc++); + *fdst++ = *fsrc++; + } +} + +static INLINE void +conv_rgbD_gamma_rgbD_linear (const Babl *conversion,unsigned char *src, + unsigned char *dst, + long samples) +{ + const Babl *space = babl_conversion_get_destination_space (conversion); + const Babl **trc = (void*)space->space.trc; + double *fsrc = (double *) src; + double *fdst = (double *) dst; + int n = samples; + + while (n--) + { + *fdst++ = babl_trc_to_linear (trc[0], *fsrc++); + *fdst++ = babl_trc_to_linear (trc[1], *fsrc++); + *fdst++ = babl_trc_to_linear (trc[2], *fsrc++); + } +} + +#define o(src, dst) \ + babl_conversion_new (src, dst, "linear", conv_ ## src ## _ ## dst, NULL) + +int init (void); + +int +init (void) +{ + const Babl *rgbaD_linear = babl_format_new ( + babl_model ("RGBA"), + babl_type ("double"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + babl_component ("A"), + NULL); + const Babl *rgbAD_linear = babl_format_new ( + babl_model ("RaGaBaA"), + babl_type ("double"), + babl_component ("Ra"), + babl_component ("Ga"), + babl_component ("Ba"), + babl_component ("A"), + NULL); + const Babl *rgbaD_gamma = babl_format_new ( + babl_model ("R'G'B'A"), + babl_type ("double"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + babl_component ("A"), + NULL); + const Babl *rgbAD_gamma = babl_format_new ( + babl_model ("R'aG'aB'aA"), + babl_type ("double"), + babl_component ("R'a"), + babl_component ("G'a"), + babl_component ("B'a"), + babl_component ("A"), + NULL); + const Babl *rgbD_linear = babl_format_new ( + babl_model ("RGB"), + babl_type ("double"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + NULL); + const Babl *rgbD_gamma = babl_format_new ( + babl_model ("R'G'B'"), + babl_type ("double"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), + NULL); + + o (rgbAD_linear, rgbAD_gamma); + o (rgbaD_linear, rgbAD_gamma); + o (rgbaD_linear, rgbaD_gamma); + o (rgbaD_gamma, rgbaD_linear); + o (rgbD_linear, rgbD_gamma); + o (rgbD_gamma, rgbD_linear); + o (rgbaD_linear, rgbD_linear); + o (rgbaD_gamma, rgbD_gamma); + + return 0; +} + diff --git a/extensions/gggl-table-lies.c b/extensions/gggl-table-lies.c index 6cce2ba..88da9b6 100644 --- a/extensions/gggl-table-lies.c +++ b/extensions/gggl-table-lies.c @@ -302,6 +302,38 @@ conv_ga16_gaF (const Babl *conversion,unsigned char *src, unsigned char *dst, lo #define conv_gA16_gAF conv_ga16_gaF #define conv_g16_gF conv_16_F +static void +conv_rgbafloat_linear_cairo32_le (const Babl *conversion,unsigned char *src_char, + unsigned char *dst, + long samples) +{ + long n = samples; + float *src = (float*)src_char; + + while (n--) + { + float alpha = src[3] * 255; +#define BABL_ALPHA_THRESHOLD 0.000000152590219 + + if (alpha < BABL_ALPHA_THRESHOLD) + { + *(int *)dst = 0; + } + else + { + if (alpha > 255) alpha = 255; +#define div_255(a) ((((a)+128)+(((a)+128)>>8))>>8) + dst[0] = src[2] * alpha + 0.5f; + dst[1] = src[1] * alpha + 0.5f; + dst[2] = src[0] * alpha + 0.5f; + dst[3] = alpha + 0.5f; + } + src += 4; + dst += 4; + } +} + + int init (void); int @@ -428,6 +460,26 @@ init (void) babl_component ("Y"), NULL); + int testint = 23; + char *testchar = (char*) &testint; + int littleendian = (testchar[0] == 23); + + if (littleendian) + { + const Babl *f32 = babl_format_new ( + "name", "cairo-ARGB32", + babl_model ("R'aG'aB'aA"), + babl_type ("u8"), + babl_component ("B'a"), + babl_component ("G'a"), + babl_component ("R'a"), + babl_component ("A"), + NULL + ); + babl_conversion_new (babl_format ("RGBA float"), f32, "linear", + conv_rgbafloat_linear_cairo32_le, NULL); + } + #define o(src, dst) \ babl_conversion_new (src, dst, "linear", conv_ ## src ## _ ## dst, NULL) diff --git a/extensions/gggl-table.c b/extensions/gggl-table.c index 0ce0353..37d68dc 100644 --- a/extensions/gggl-table.c +++ b/extensions/gggl-table.c @@ -164,6 +164,7 @@ conv_F_8 (const Babl *conversion,unsigned char *src, unsigned char *dst, long sa } } + static void conv_F_16 (const Babl *conversion,unsigned char *src, unsigned char *dst, long samples) { diff --git a/extensions/meson.build b/extensions/meson.build index d04ad67..f452417 100644 --- a/extensions/meson.build +++ b/extensions/meson.build @@ -2,6 +2,7 @@ extension_names = [ '16bit', 'cairo', 'CIE', + 'double', 'fast-float', 'float-half', 'float', diff --git a/extensions/two-table.c b/extensions/two-table.c index 4b263cc..880adff 100644 --- a/extensions/two-table.c +++ b/extensions/two-table.c @@ -205,6 +205,17 @@ init (void) if (littleendian) { + const Babl *f32 = babl_format_new ( + "name", "cairo-ARGB32", + babl_model ("R'aG'aB'aA"), + babl_type ("u8"), + babl_component ("B'a"), + babl_component ("G'a"), + babl_component ("R'a"), + babl_component ("A"), + NULL + ); + const Babl *f24 = babl_format_new ( "name", "cairo-RGB24", babl_model ("R'G'B'"), -- 2.30.2